#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <set>
#include <map>
#include <vector>
#include "gmsh.h"

using namespace std;
typedef double Real;

int main(int argc, char *argv[])
{
	const string grid_file("rae2822_level4.m4.msh");
//	ifstream in(grid_file.c_str());
	ifstream in(argv[1]);

	if(!in.good())
	{
		cout << "Input grid does not exit.\n";
		return 0;
	}


	int format=0, size=0;
	Real version = 1.0;

	std::map<unsigned int, unsigned int> nodetrans;

//	ofstream out("rae2822_level4.msh");
	ofstream out(argv[2]);
	string line;
	while (true)
	{
		std::getline(in, line);
		if (in.eof())
			break;

		out << line <<endl;
		if (line.find("$MeshFormat") == static_cast<std::string::size_type>(0)){}
		else if (line.find("$PhysicalNames") == static_cast<std::string::size_type>(0)){}
		else if (line.find("$NOD") == static_cast<std::string::size_type>(0) ||
				 line.find("$NOE") == static_cast<std::string::size_type>(0) ||
				 line.find("$Nodes") == static_cast<std::string::size_type>(0)) {}

		else if (line.find("$ELM") == static_cast<std::string::size_type>(0) ||
				 line.find("$Elements") == static_cast<std::string::size_type>(0))
		{
			int num_elem;
			std::getline(in, line);
			istringstream iss(line);
			iss >> num_elem ;
			out << line <<endl;
			for (unsigned int iel=0; iel<num_elem; ++iel)
			{
				unsigned int
				id, type, type_out,
				physical=1, elementary=1, partition = 1, node_id,
				nnodes=0, ntags;

				std::getline(in, line);
				istringstream iss(line);

				iss >> id >> type >> ntags;
				if(ntags ==2)
					iss >> physical >> elementary;
				else if(ntags == 3)
					iss >> physical >> elementary >> partition;


				vector<int> node_in, node_out;
				if(type == TRI12)
				{
					type_out = TRI6;
					for (unsigned int i=0; i<12; i++)
					{
						iss >> node_id;
						node_in.push_back(node_id);
					}
					node_out.push_back(node_in[0]);
					node_out.push_back(node_in[1]);
					node_out.push_back(node_in[2]);
					node_out.push_back(node_in[4]);
					node_out.push_back(node_in[7]);
					node_out.push_back(node_in[10]);
				}
				else if(type == TRI15F)
				{
					type_out = TRI6;
					for (unsigned int i=0; i<12; i++)
					{
						iss >> node_id;
						node_in.push_back(node_id);
					}
					node_out.push_back(node_in[0]);
					node_out.push_back(node_in[1]);
					node_out.push_back(node_in[2]);
					node_out.push_back(node_in[4]);
					node_out.push_back(node_in[7]);
					node_out.push_back(node_in[10]);
				}
				else if(type == QUAD25)
				{
					type_out = QUAD8;
					for (unsigned int i=0; i<25; i++)
					{
						iss >> node_id;
						node_in.push_back(node_id);
					}
					node_out.push_back(node_in[0]);
					node_out.push_back(node_in[1]);
					node_out.push_back(node_in[2]);
					node_out.push_back(node_in[3]);
					node_out.push_back(node_in[5]);
					node_out.push_back(node_in[8]);
					node_out.push_back(node_in[11]);
					node_out.push_back(node_in[14]);
				}
				else if(type == HEX125)
				{
					type_out = HEX20;
					for (unsigned int i=0; i<125; i++)
					{
						iss >> node_id;
						node_in.push_back(node_id);
					}
					node_out.push_back(node_in[0]);
					node_out.push_back(node_in[1]);
					node_out.push_back(node_in[2]);
					node_out.push_back(node_in[3]);
					node_out.push_back(node_in[4]);
					node_out.push_back(node_in[5]);
					node_out.push_back(node_in[6]);
					node_out.push_back(node_in[7]);

					node_out.push_back(node_in[9]);
					node_out.push_back(node_in[12]);
					node_out.push_back(node_in[15]);
					node_out.push_back(node_in[18]);
					node_out.push_back(node_in[21]);
					node_out.push_back(node_in[24]);
					node_out.push_back(node_in[27]);
					node_out.push_back(node_in[30]);
					node_out.push_back(node_in[33]);
					node_out.push_back(node_in[36]);
					node_out.push_back(node_in[39]);
					node_out.push_back(node_in[42]);
				}
				else if(type == EDGE5)
				{
					type_out = EDGE3;
					for (unsigned int i=0; i<5; i++)
					{
						iss >> node_id;
						node_in.push_back(node_id);
					}
					node_out.push_back(node_in[0]);
					node_out.push_back(node_in[1]);
					node_out.push_back(node_in[3]);
				}
				else
				{
					cout << "non resolved type." << type <<endl;
				}

				out << id <<" "<< type_out <<" "<< 2 << " " << physical <<" "<< elementary <<" ";
				for (unsigned int i=0; i<node_out.size(); i++)
				{
					out << node_out[i] << " ";
				}
				out <<endl;

			}
		}



	}
}
